package com.faner4cloud.yun.common.util.batch;

import java.util.Collection;
import java.util.Objects;

/**
 * 批量操作
 * </p>
 *
 * 场景1. 批量执行，并返回影响行数累加值 :
 *
 * <pre>
 * int cnt = Batchs.from(Arrays.asList(1, 2, 3, 4, 5), 10).sumEach((context) -> {
 *   return sqlSession.insert("**Mapper.sqlId", context.getData());
 * });
 *
 * </pre>
 *
 * 场景2. 使用Stream流来累加影响行数（实现场景一的功能）:
 *
 * <pre>
 * Batchs.from(Arrays.asList(1, 2, 3, 4, 5), 10).each((context) -> {
 *   return sqlSession.insert("**Mapper.sqlId", context.getData());
 * }).reduce(0, (result, val) -> result = result + val);
 *
 * </pre>
 *
 * 场景3. 批处理返回值为保存到List里:
 *
 * <pre>
 * List<String> batchResult= Batchs.from(Arrays.asList(1, 2, 3, 4, 5), 10).listEach((context) -> {
 * //做一些业务逻辑
 * return "Java对象"
 * });
 * </pre>
 *
 * 场景4. 批处理返回值为void:
 *
 * <pre>
 * Batchs.from(Arrays.asList(1, 2, 3, 4, 5), 10).each((context) -> {
 *   // 做一些业务逻辑，void最后需要返回null。最后调用Stream的count()触发批处理。
 *   return null;
 * }).count();
 * </pre>
 *
 */
public final class Batchs {
	private Batchs() {
		throw new AssertionError("不支持实例化！");
	}

	/**
	 * 以同步阻塞的方式分批执行数据。
	 *
	 * @param data 数据集，不能为null
	 * @param batchSize 每批多少条数据
	 * @return 返回一个可分批执行的接口
	 * @exception NullPointerException data为null
	 * @exception IllegalArgumentException batchSize小于0
	 * @since 2018年7月11日
	 */
	@SuppressWarnings("unchecked")
	public static <T> Batchable<T> from(Collection<T> data, int batchSize) {
		Objects.requireNonNull(data, "用于分批执行的源数据不能为空");
		if (batchSize < 1) {
			throw new IllegalArgumentException("每批数据的个数不能小于0");
		}
		return new SynchronousBatch<>((T[]) data.toArray(), batchSize);
	}
}


